package com.sansecy.customview.tab;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.core.view.ViewCompat;
import androidx.viewpager.widget.ViewPager;

import android.text.Layout;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;


import com.google.android.material.animation.AnimationUtils;

public class CustomTabLayout extends HorizontalScrollView implements View.OnClickListener {

    private View indicator;
    private int leftPadding;
    private int topPadding;
    private int rightPadding;
    private int bottomPadding;
    private int selectedPosition = 0;
    private LinearLayout tabContainer;
    private ValueAnimator animator;
    private TabLayoutOnPageChangeListener onPageChangeListener;
    private int indicatorWidth;
    private int textSize = 12;
    private ViewPager viewPager;
    private List<OnTabSelectedListener> tabSelectedListeners;
    private int textColor;
    //滚动模式，固定还是滚动
    private int mode;
    public int indicatorGravity;
    public int indicatorColor;
    public static final int MODE_SCROLLABLE = 0;
    public static final int MODE_FIXED = 1;
    public int contentStartMargin = 0;

    public void addOnTabSelectedListener(OnTabSelectedListener onTabSelectedListener) {
        if (tabSelectedListeners == null) {
            tabSelectedListeners = new ArrayList<>();
        }
        tabSelectedListeners.add(onTabSelectedListener);
    }

    public CustomTabLayout(Context context) {
        this(context, null);
    }

    public CustomTabLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setHorizontalScrollBarEnabled(false);
        setFillViewport(true);
        LinearLayout linearLayout = new LinearLayout(context);
        linearLayout.setLayoutParams(new HorizontalScrollView.MarginLayoutParams(500, 500));
        linearLayout.setOrientation(LinearLayout.VERTICAL);
        tabContainer = new LinearLayout(context);
        tabContainer.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        tabContainer.setOrientation(LinearLayout.HORIZONTAL);
        linearLayout.addView(tabContainer);
        indicator = new View(context);
        indicator.setBackgroundColor(Color.RED);
        indicator.setLayoutParams(new LinearLayoutCompat.LayoutParams(0, 0));
        linearLayout.addView(indicator);
        textColor = Color.BLACK;
        indicatorGravity = Gravity.START;
        addView(linearLayout);
        //设置默认滚动模式
        mode = MODE_FIXED;
    }

    public void setScrollMode(int mode) {
        this.mode = mode;
        for (int i = 0; i < tabContainer.getChildCount(); i++) {
            View child = tabContainer.getChildAt(i);
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
            if (mode == MODE_FIXED) {
                //固定模式下
                //按照权重分配大小
                lp.width = 0;
                lp.weight = 1;
            } else {
                lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
                lp.weight = 0;
                child.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
            }
            child.setLayoutParams(lp);
        }
    }

    void updateTabViews(final boolean requestLayout) {
        for (int i = 0; i < tabContainer.getChildCount(); i++) {
            View child = tabContainer.getChildAt(i);
            updateTabViewLayoutParams((LinearLayout.LayoutParams) child.getLayoutParams());
            if (requestLayout) {
                child.requestLayout();
            }
        }
    }

    private void updateTabViewLayoutParams(LinearLayout.LayoutParams lp) {
        if (mode == MODE_FIXED) {
            lp.width = 0;
            lp.weight = 1;
        } else {
            lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
            lp.weight = 0;
        }
    }

    public void setIndicatorWidth(int width) {
        this.indicatorWidth = width;
        ViewGroup.LayoutParams layoutParams = indicator.getLayoutParams();
        layoutParams.width = width;
        indicator.setLayoutParams(layoutParams);
    }


    /**
     * 设置指示符对齐方式
     *
     * @param indicatorGravity 参数可以是Gravity.START,CENTER,END
     */
    public void setIndicatorGravity(int indicatorGravity) {
        this.indicatorGravity = indicatorGravity;
    }

    /**
     * 设置指示符的颜色
     *
     * @param indicatorColor 颜色代码，通过ContextCompat。getColor()从资源文件获取
     *                       通过Color.Parse()从字符串生成
     */
    public void setIndicatorColor(@ColorInt int indicatorColor) {
        this.indicatorColor = indicatorColor;
        this.indicator.setBackgroundColor(indicatorColor);
    }

    /**
     * 设置文字大小
     *
     * @param textSize 文字大小，单位是sp
     */
    public void setTextSize(int textSize) {
        this.textSize = textSize;
        for (int i = 0; i < tabContainer.getChildCount(); i++) {
            View child = tabContainer.getChildAt(i);
            if (child instanceof TextView) {
                TextView textView = (TextView) child;
                textView.setTextSize(textSize);
            }
        }
        setDefaultIndicatorWidth();
    }

    /**
     * 添加一个TextView到tabContainer
     *
     * @param title 标题名称
     * @return 新添加的TextView
     */
    public TextView addTitle(String title) {
        return addTitle(title, false);
    }

    /**
     * @param title
     * @param moveToThis
     * @return
     */
    public TextView addTitle(String title, boolean moveToThis) {
        final TextView textView = createTextView(title);
        tabContainer.addView(textView);
        if (moveToThis) {
            textView.post(new Runnable() {
                @Override
                public void run() {
                    if (indicatorWidth == 0) {
                        indicatorWidth = textView.getWidth() - textView.getPaddingLeft() - textView.getPaddingRight();
                    }
                    ViewGroup.LayoutParams layoutParams = indicator.getLayoutParams();
                    layoutParams.width = indicatorWidth;
                    indicator.setLayoutParams(layoutParams);
                    setSelectedPosition(tabContainer.indexOfChild(textView));
                }
            });
        } else {
            setDefaultIndicatorWidth();
        }
        return textView;
    }

    public void setTextColor(@ColorInt int color) {
        if (textColor == color) {
            return;
        }
        for (int i = 0; i < tabContainer.getChildCount(); i++) {
            View child = tabContainer.getChildAt(i);
            if (child instanceof TextView) {
                textColor = color;
                TextView textView = (TextView) child;
                textView.setTextColor(textColor);
            }
        }
    }

    private float approximateLineWidth(Layout layout, int line, float textSize) {
        return layout.getLineWidth(line) * (textSize / layout.getPaint().getTextSize());
    }

    public void setTitle(List<String> titles) {
        tabContainer.removeAllViews();
        for (int i = 0; i < titles.size(); i++) {
            String s = titles.get(i);
            tabContainer.addView(createTextView(s));
        }
        setDefaultIndicatorWidth();
        addOnTabSelectedListener(new OnTabSelectedListener() {
            @Override
            public void onTabSelected(int position) {
                if (viewPager != null) {
                    viewPager.setCurrentItem(position);
                }
            }

            @Override
            public void onTabUnselected(int position) {

            }

            @Override
            public void onTabReselected(int position) {

            }
        });
    }


    /**
     * 创建TextView
     *
     * @param text 要显示的文字
     * @return textView
     */
    private TextView createTextView(String text) {
        TextView textView = new TextView(getContext());
        textView.setText(text);
        textView.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
        textView.setTextSize(textSize);
        textView.setTextColor(textColor);
        textView.setMaxLines(1);
        textView.setGravity(Gravity.CENTER);
        textView.setOnClickListener(this);
        return textView;
    }

    /**
     * 给每个TextView设置内边距
     *
     * @param left   左内边距
     * @param top    上内边距
     * @param right  右内边距
     * @param bottom 下内边距
     */
    public void setTextPadding(int left, int top, int right, int bottom) {
        this.leftPadding = left;
        this.topPadding = top;
        this.rightPadding = right;
        this.bottomPadding = bottom;
        if (mode == MODE_FIXED) {
            setFillViewport(true);
            tabContainer.getLayoutParams().width = -1;
        } else {
            setFillViewport(true);
        }
        for (int i = 0; i < tabContainer.getChildCount(); i++) {
            View child = tabContainer.getChildAt(i);
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
            if (mode == MODE_FIXED) {
                //固定模式下
                //按照权重分配大小
                lp.width = 0;
                lp.weight = 1;
            } else {
                lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
                lp.weight = 0;
                child.setPadding(left, top, right, bottom);
            }
            child.setLayoutParams(lp);
        }
        setDefaultIndicatorWidth();
    }

    /**
     * 设置指示符的高度
     *
     * @param height 高度值，以px为单位
     */
    public void setIndicatorHeight(int height) {
        ViewGroup.LayoutParams layoutParams = indicator.getLayoutParams();
        layoutParams.height = height;
        indicator.setLayoutParams(layoutParams);
    }

    /**
     * 设置默认指示符宽度
     * 默认宽度以第一个文字的宽度为指示符宽度
     */
    private void setDefaultIndicatorWidth() {
        if (tabContainer.getChildCount() > 0) {
            final View child = tabContainer.getChildAt(0);
            //宽度与设置的indicatorWidth相等，不进行操作
            if (child.getLayoutParams().width == indicatorWidth) {
                return;
            }
            //采用post方式是因为在子视图没有初始化完成是获取不到childView宽度的
            child.post(new Runnable() {
                @Override
                public void run() {
                    ViewGroup.LayoutParams layoutParams = indicator.getLayoutParams();
                    if (indicatorWidth != 0) {
                        //将系统的指示符宽度设置为indicatorWidth
                        layoutParams.width = indicatorWidth;
                    } else {
                        //如果indicatorWidth为0，取第一个文字的宽度作为indicatorWidth
                        indicatorWidth = child.getWidth() - child.getPaddingLeft() - child.getPaddingRight();
                    }
                    indicator.setLayoutParams(layoutParams);
                    if (indicatorGravity == Gravity.START) {
                        float x = child.getX();
                        indicator.setX(x + child.getPaddingLeft());
                    } else if (indicatorGravity == Gravity.CENTER) {
                        int x = (int) child.getX() + child.getWidth() / 2 - indicator.getWidth() / 2;
                        indicator.setX(x);
                    }
                }
            });
        }
    }

    @Override
    public void onClick(final View v) {
        int newPosition = tabContainer.indexOfChild(v);
        if (newPosition == -1) {
            return;
        }
        //点击的不是同一个TextView
        if (newPosition != this.selectedPosition) {
            setSelectedPosition(newPosition);

            if (tabSelectedListeners != null) {
                for (OnTabSelectedListener onTabSelectedListener : tabSelectedListeners) {
                    if (onTabSelectedListener != null) {
                        onTabSelectedListener.onTabSelected(newPosition);
                    }
                }
            }
        } else {
            //是同一个TextView
            //触发重复选中的回调
            if (tabSelectedListeners != null) {
                for (OnTabSelectedListener onTabSelectedListener : tabSelectedListeners) {
                    if (onTabSelectedListener != null) {
                        onTabSelectedListener.onTabReselected(newPosition);
                    }
                }
            }
        }
    }

    ValueAnimator mScrollAnimator;
    private void ensureScrollAnimator() {
        if (mScrollAnimator == null) {
            mScrollAnimator = new ValueAnimator();
            mScrollAnimator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
            mScrollAnimator.setDuration(300);
            mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animator) {
                    scrollTo((int) animator.getAnimatedValue(), 0);
                }
            });
        }
    }

    private static final String TAG = "CustomTabLayout-App";
    /**
     * 匹配ViewPager
     *
     * @param viewPager 要连接的viewPager
     */
    public void setupWithViewPager(@Nullable ViewPager viewPager) {
        if (viewPager != null) {
            this.viewPager = viewPager;
            this.viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener());
        }
    }

    /**
     * 返回存储tab的容器
     *
     * @return tabContainer
     */
    public ViewGroup getTabContainer() {
        return tabContainer;
    }

    /**
     * 返回已选中的位置
     *
     * @return 已选中的position
     */
    public int getSelectedPosition() {
        return selectedPosition;
    }

    /**
     * 返回下一个位置
     *
     * @return
     */
    public int getNextPosition() {
        int nextPosition = selectedPosition + 1;
        if (nextPosition > getChildCount() - 1) {
            return -1;
        }
        return nextPosition;
    }

    public void setSelectedPosition(int selectedPosition) {
        setSelectedPosition(selectedPosition, 0);
    }

    public void setSelectedPosition(int selectedPosition, float positionOffset) {
        this.selectedPosition = selectedPosition;
        //动画当中，取消动画
        if (animator != null && animator.isRunning()) {
            animator.cancel();
        }
        View view = tabContainer.getChildAt(selectedPosition);

        int nextLeft = 0;
        //得到指示符的X位置
        int x = (int) indicator.getX();
        if (indicatorGravity == Gravity.START) {
            //得到点击的视图的左侧
            nextLeft = view.getPaddingLeft() + view.getLeft();
            //得到两者的差值，通常是将要到达的位置减去当前位置
            int offset = nextLeft - x;
            //设置X的位置
        } else if (indicatorGravity == Gravity.CENTER) {
            nextLeft = view.getLeft() + view.getWidth() / 2 - indicator.getWidth() / 2;
        } else if (indicatorGravity == Gravity.END) {
            nextLeft = view.getRight() - view.getPaddingRight();
        }
        animator = ObjectAnimator.ofFloat(x, nextLeft);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                indicator.setX(value);
            }
        });
        animator.setDuration(300);
        animator.start();

        final int startScrollX = getScrollX();
        final int targetScrollX = calculateScrollXForTab(selectedPosition, 0);
        if (startScrollX != targetScrollX) {
            ensureScrollAnimator();
            mScrollAnimator.setIntValues(startScrollX, targetScrollX);
            mScrollAnimator.start();
        }
    }

    int height;
    int width;

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

//    @Override
//    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        if (isInEditMode()) {
//            setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0), dpToPx(72));
//        } else {
////            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//            setMeasuredDimension(1000,1000);
//        }
//    }

    public class TabLayoutOnPageChangeListener implements ViewPager.OnPageChangeListener {
        private int mPreviousScrollState;
        private int mScrollState;

        public TabLayoutOnPageChangeListener() {

        }

        public void onPageScrollStateChanged(int state) {
            mPreviousScrollState = mScrollState;
            mScrollState = state;
        }

        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            //如果之前的滚动状态不是闲置，并且现在的滚动状态不是安定，那么就更新指示符
            final boolean updateIndicator = !(mScrollState == ViewPager.SCROLL_STATE_SETTLING
                    && mPreviousScrollState == ViewPager.SCROLL_STATE_IDLE);
            if (!updateIndicator) {
                return;
            }
            //这里的position得到的是左侧第一个显示的视图的position
            if (position > tabContainer.getChildCount() - 1) {
                return;
            }

            if (positionOffset > 0 && positionOffset <= 1) {
                //滚动指示符
                //需要滚动的距离
                View view = tabContainer.getChildAt(position);
                int leftOffset = 0;
                int tabOffset = 0;
                //表示发生了viewPager的滚动偏移
                if (indicatorGravity == Gravity.START) {
                    //得到点击的视图的左侧
                    leftOffset = view.getLeft() + view.getPaddingLeft();
                    if (position + 1 < tabContainer.getChildCount()) {
                        View nextView = tabContainer.getChildAt(position + 1);
                        tabOffset = nextView.getLeft() - view.getLeft() - view.getPaddingLeft() + nextView.getPaddingLeft();
                    }
                    //设置X的位置
                } else if (indicatorGravity == Gravity.CENTER) {
                    leftOffset = view.getRight() - view.getWidth() / 2 - indicator.getWidth() / 2;
                    if (position + 1 < tabContainer.getChildCount()) {
                        View nextView = tabContainer.getChildAt(position + 1);
                        tabOffset = nextView.getLeft() - view.getLeft() - view.getPaddingLeft() + nextView.getPaddingLeft();
                    }
                } else if (indicatorGravity == Gravity.END) {
                    leftOffset = view.getRight() - view.getPaddingRight() - indicator.getWidth();
                    if (selectedPosition + 1 <= tabContainer.getChildCount() - 1) {
                        View nextView = tabContainer.getChildAt(position + 1);
                        tabOffset = nextView.getRight() - nextView.getPaddingRight() - indicator.getWidth() - (view.getRight() - view.getPaddingRight() - indicator.getWidth());
                    }
                }
                indicator.setX(leftOffset + (positionOffset) * tabOffset);
                scrollTo(calculateScrollXForTab(position, positionOffset), 0);
            }
        }

        private static final String TAG = "TabLayoutOnPageChangeLi-App";

        public void onPageSelected(int position) {
            if (getSelectedPosition() != position
                    && position < tabContainer.getChildCount()) {
                //选择选项卡，只有在我们没有被拖动/结算时才更新指标（因为onPageScrolled会处理它）。
                final boolean updateIndicator = mScrollState == ViewPager.SCROLL_STATE_IDLE
                        || (mScrollState == ViewPager.SCROLL_STATE_SETTLING
                        && mPreviousScrollState == ViewPager.SCROLL_STATE_IDLE);
                //这儿离的position是被选中的position的视图
                if (updateIndicator) {
                    setSelectedPosition(position);
                }
            }
        }
    }
    private int calculateScrollXForTab(int position, float positionOffset) {
        if (mode == MODE_SCROLLABLE) {
            final View selectedChild = tabContainer.getChildAt(position);
            final View nextChild = position + 1 < tabContainer.getChildCount()
                    ? tabContainer.getChildAt(position + 1)
                    : null;
            final int selectedWidth = selectedChild != null ? selectedChild.getWidth() : 0;
            final int nextWidth = nextChild != null ? nextChild.getWidth() : 0;

            // base scroll amount: places center of tab in center of parent
            int scrollBase = selectedChild.getLeft() + (selectedWidth / 2) - (getWidth() / 2);
            // offset amount: fraction of the distance between centers of tabs
            int scrollOffset = (int) ((selectedWidth + nextWidth) * 0.5f * positionOffset);

            return (ViewCompat.getLayoutDirection(CustomTabLayout.this) == ViewCompat.LAYOUT_DIRECTION_LTR)
                    ? scrollBase + scrollOffset
                    : scrollBase - scrollOffset;
        }
        return 0;
    }
    int dpToPx(int dps) {
        return Math.round(getResources().getDisplayMetrics().density * dps);
    }

    public interface OnTabSelectedListener {

        public void onTabSelected(int position);

        public void onTabUnselected(int position);

        public void onTabReselected(int position);
    }
}